/*
 *  main.c
 *  Angel & Demon - Tenshi to Akuma
 *
 *  Created by Si-Mohamed Lamraoui on 29/10/10.
 *
 */

#include "game.h"


/**
 *
 */
int init(void) {
	
	
	if(SDL_Init(SDL_INIT_VIDEO) < 0) {
		//fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
		error("Couldn't initialize SDL", SDL_GetError());
		return 1;
	}
	
	screen = SDL_SetVideoMode(SCREEN_W, SCREEN_H, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
	if(screen == NULL) {
		//fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
		error("Couldn't set video mode", SDL_GetError());
		SDL_Quit();
		return 1;
	}
	
	SDL_EnableKeyRepeat(1,100);
	
	// Set random seed
	srand(time(NULL));
	
	// Clear monsters matrix
	int i,j;
	for (i=0; i<NB_CASE_W; i++) {
		for (j=0; j<NB_CASE_H; j++) {
			monster[i][j] = NONE;
		}
	}
	
	// Init and load fonts
	TTF_Init();
	font_20 = TTF_OpenFont("font/TECHNOID.TTF", 20);
	font_30 = TTF_OpenFont("font/TECHNOID.TTF", 30);
	
	// Load images and animations
	map = load_image("images/map_new2.bmp");
	monster_demon = load_colorkey_image("images/demon.bmp");
	monster_angel = load_colorkey_image("images/angel.bmp");
	player_up = load_colorkey_image("images/player_up.bmp");
	player_down = load_colorkey_image("images/player_down.bmp");
	player_left = load_colorkey_image("images/player_left.bmp");
	player_right = load_colorkey_image("images/player_right.bmp");
	demon_mini = load_colorkey_image("images/demon_mini.bmp");
	angel_mini = load_colorkey_image("images/angel_mini.bmp");
	msg_akuma = load_colorkey_image("images/m_akuma.bmp");
	msg_tenshi = load_colorkey_image("images/m_tenshi.bmp"); 
	hud = load_colorkey_image("images/hud1.bmp"); 
	light1 = load_colorkey_image("images/light1.bmp");
	title = load_image("images/title.bmp");
	anim_demon_hat = ANIM_create("images/demon_hat_", 7, 20*MS, 150);
	anim_angel_hat = ANIM_create("images/angel_hat_", 7, 20*MS, 150);

	chrono = 60;
	score = 0;
	chaine = 0;
	angel_bar = 0;
	tmp_angel_bar = 0;
	demon_bar = 0;
	tmp_demon_bar = 0;
	nb_demon = 0;
	nb_angel = 0;
	
	posAbs.x = LEFT_ANGLE_X;
	posAbs.y = LEFT_ANGLE_Y;
	pos_x = 5;
	pos_y = 5;
	orient = DOWN;
	state = DEMON;
	old_state = NONE;
	
	draw_msg = 0;
	animation = FALSE;
	animation_light = FALSE;
	animation_death = FALSE;
	anim_y = 0;
	alpha_light = 255;
	
	// Init timers
	timer_restart(&timer_anim_monster);
	timer_restart(&timer_anim_light);
	timer_restart(&timer_chrono);
	timer_restart(&timer_move);
	
	return 0;
}



/**
 *
 */
int game(void)
{
	
	display_title(screen);
	
	float tmp;
	int width;
	int i,j;
	int done = FALSE;
	while(!done) {
		
		#ifdef PSP
			done = psp_event_listener();
		#else
			done = basic_event_listener();
		#endif

		// Update chrono
		if(timer_state(&timer_chrono, 1000*MS)) {
			timer_restart(&timer_chrono);
			chrono--;
		}
		if(chrono==-1) {
			display_gameover(screen);
			chrono = 60;
			score = 0;
			chaine = 0;
			angel_bar = 0;
			demon_bar = 0;
			tmp_angel_bar = 0;
			tmp_demon_bar = 0;
			nb_demon = 0;
			nb_angel = 0;
			pos_x = 5;
			pos_y = 5;
			old_state = NONE;
			orient = DOWN;
			animation = FALSE;
			animation_light = FALSE;
			animation_death = FALSE;
			for (i=0; i<NB_CASE_W; i++) {
				for (j=0; j<NB_CASE_H; j++) {
					monster[i][j] = NONE;
				}
			}
			timer_restart(&timer_move);
		}
		
		
		// Set player sprite orientation
		SDL_Surface *player = NULL;
		switch (orient) {
			case UP:
				player = player_up;
				break;
			case DOWN:
				player = player_down;
				break;
			case LEFT:
				player = player_left;
				break;
			case RIGHT:
				player = player_right;
				break;
		}
		
		// Clear screen
		//SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
		
		// Display background
		blit_image(map, 0, 0, screen);
		
		
		// If the map is empty, we fill with new monsters
		if(animation==FALSE) {
			int empty = TRUE;
			animation = TRUE;
			for (i=0; i<NB_CASE_W; i++) {
				for (j=0; j<NB_CASE_H; j++) {
					if(monster[i][j]==DEMON || monster[i][j]==ANGEL) {
						empty = FALSE;
						animation = FALSE;
						break;
					}
				}
			}
			if(empty==TRUE) {
				animation_death = FALSE;
				int type = 0, x = 0, y = 0;
				for(i=0; i<BASE_MOB; i++) {
					do {
						x = rand()%11; 
						y = rand()%11;
						type = rand()%2+1;
					} while(x==pos_x && y==pos_y);
					if(type==1)
						monster[x][y] = DEMON;
					else
						monster[x][y] = ANGEL;
				}
			}
		}
		
		SDL_Rect pos;
		SDL_Surface *image = NULL;
		if(animation==TRUE) {
			timer_restart(&timer_anim_monster);
			animation = ACTIVE;
			anim_y = 100;
		}
		if(animation==ACTIVE) {
			if(timer_state(&timer_anim_monster, 100)) {
				timer_restart(&timer_anim_monster);
				anim_y-=4;
				if(anim_y==0)
					animation = FALSE;
			}
			for (i=0; i<NB_CASE_W; i++) {
				for (j=0; j<NB_CASE_H; j++) {
					if(i==pos_x && j==pos_y) {
						posAbs.x = UP_ANGLE_X + (pos_x*CASE_SIZE) - (pos_y*(CASE_SIZE));
						posAbs.y = UP_ANGLE_Y + (pos_y*(CASE_SIZE/2)) + (pos_x*CASE_SIZE/2);
						blit_image(player, posAbs.x, posAbs.y, screen);
						posAbs.y = posAbs.y - 10;
						if(state==DEMON) {
							image = ANIM_getImage(anim_demon_hat);
						} else {
							image = ANIM_getImage(anim_angel_hat);
						}
						if(image==NULL) {
							error("Null pointer", "game");
							return 1;
						}
						blit_image(image, posAbs.x, posAbs.y, screen);
					} else if(monster[i][j]==DEMON) {
						pos.x = UP_ANGLE_X + (i*CASE_SIZE) - (j*(CASE_SIZE));
						pos.y = UP_ANGLE_Y + (j*(CASE_SIZE/2)) + (i*CASE_SIZE/2) - anim_y;
						blit_image(monster_demon, pos.x, pos.y, screen);
					} else if(monster[i][j]==ANGEL) {
						pos.x = UP_ANGLE_X + (i*CASE_SIZE) - (j*(CASE_SIZE));
						pos.y = UP_ANGLE_Y + (j*(CASE_SIZE/2)) + (i*CASE_SIZE/2) - anim_y;
						blit_image(monster_angel, pos.x, pos.y, screen);
					}
				}
			}
			
		} else {
		// Display PLAYER and ANGEL or DEMON
		for (i=0; i<NB_CASE_W; i++) {
			for (j=0; j<NB_CASE_H; j++) {
				// Display player and player animation
				if(i==pos_x && j==pos_y) {
					posAbs.x = UP_ANGLE_X + (pos_x*CASE_SIZE) - (pos_y*(CASE_SIZE));
					posAbs.y = UP_ANGLE_Y + (pos_y*(CASE_SIZE/2)) + (pos_x*CASE_SIZE/2);
					blit_image(player, posAbs.x, posAbs.y, screen);
					posAbs.y = posAbs.y - 10;
					if(state==DEMON) {
						image = ANIM_getImage(anim_demon_hat);
					} else {
						image = ANIM_getImage(anim_angel_hat);
					}
					if(image==NULL) {
						error("Null pointer", "game");
						return 1;
					}
					blit_image(image, posAbs.x, posAbs.y, screen);
					// Changing state animation
					if(animation_light==TRUE) {
						alpha_light = 255;
						animation_light = ACTIVE;
						timer_restart(&timer_anim_light);
					}
					if(animation_light==ACTIVE) {
						if(timer_state(&timer_anim_light, 1*MS)) {
							timer_restart(&timer_anim_light);
							alpha_light -= 5;
						}
						if(alpha_light<=0) {
							alpha_light = 0;
							animation_light = FALSE;
						} else {
							SDL_SetAlpha(light1, SDL_SRCALPHA, alpha_light);
							blit_image(light1, posAbs.x, posAbs.y - light1->h+47, screen);
						}
					}
				} else if(monster[i][j]==DEMON) {
					pos.x = UP_ANGLE_X + (i*CASE_SIZE) - (j*(CASE_SIZE));
					pos.y = UP_ANGLE_Y + (j*(CASE_SIZE/2)) + (i*CASE_SIZE/2) - anim_y;
					blit_image(monster_demon, pos.x, pos.y, screen);
				} else if(monster[i][j]==ANGEL) {
					pos.x = UP_ANGLE_X + (i*CASE_SIZE) - (j*(CASE_SIZE));
					pos.y = UP_ANGLE_Y + (j*(CASE_SIZE/2)) + (i*CASE_SIZE/2);
					blit_image(monster_angel, pos.x, pos.y, screen);
				}
				if(animation_death==ACTIVE && i==anim_death_pos.x && j==anim_death_pos.y) {
					if(anim_death_y>50)
						animation_death = FALSE;
					anim_death_y = anim_death_y + 2;
					alpha_death = alpha_death - 9;
					if(alpha_death<0)
						alpha_death = 0;
					posMonster.x = UP_ANGLE_X + (i*CASE_SIZE) - (j*(CASE_SIZE));
					posMonster.y = UP_ANGLE_Y + (j*(CASE_SIZE/2)) + (i*CASE_SIZE/2) - anim_death_y;
					SDL_Surface *dead = NULL;
					if(anim_death_state==DEMON)
						dead = monster_demon;
					else
						dead = monster_angel;
					SDL_SetAlpha(dead, SDL_SRCALPHA, alpha_death);
					blit_image(dead, posMonster.x, posMonster.y, screen);
					SDL_SetAlpha(dead, SDL_SRCALPHA, 255);
				}
			}
		}
		}
		
		// Display all messages
		/*if(draw_msg==DEMON) {
			posMsg.x = posAbs.x - 20;
			posMsg.y = posAbs.y - 20;
			SDL_BlitSurface(msg_akuma, NULL, screen, &posMsg);
		} else if(draw_msg==ANGEL) {
			posMsg.x = posAbs.x - 20;
			posMsg.y = posAbs.y - 20;
			SDL_BlitSurface(msg_tenshi, NULL, screen, &posMsg);
		}*/
			
		// Display the hud
		blit_image(hud, 10, 21, screen);
		blit_image(demon_mini, 380, 10, screen);
		blit_image(angel_mini, 440, 10, screen);
		blit_int(score, 10, 41, font_20, screen);
		//blit_int(chaine, 10, 40, font_20, screen);
		blit_int(nb_demon, 350, 5, font_20, screen);
		blit_int(nb_angel, 410, 5, font_20, screen);
		blit_int(chrono, 10, -5, font_30, screen);
		/*if(tmp_demon_bar<demon_bar && tmp_demon_bar<100)
			tmp_demon_bar++;
		if(tmp_demon_bar>100)
			tmp_demon_bar = 100;
		if(tmp_angel_bar<angel_bar && tmp_angel_bar<100)
			tmp_angel_bar++;
		if(tmp_angel_bar>100)
			tmp_angel_bar = 100;
		SDL_Surface *bar = NULL;
		tmp = (float) tmp_angel_bar;
		tmp = (154.0/100.0)*tmp;
		width = (int) tmp;
		bar = SDL_CreateRGBSurface(SDL_HWSURFACE, width, 9, 32, 0,0,0,0);
		if(bar==NULL) {
			error("Null pointer", "game");
			return 1;
		}
		SDL_FillRect(bar, NULL, SDL_MapRGB(bar->format, 220, 220, 255));
		if(angel_bar==100) {
			anim_bar_z += 100;
			if(anim_bar_z>255)
				anim_bar_z = 0;
			if(anim_bar_z<128)
				SDL_SetAlpha(bar, SDL_SRCALPHA, 0);
			else
				SDL_SetAlpha(bar, SDL_SRCALPHA, 255);
		}
		blit_image(bar, 11, 22, screen);
		tmp = (float) tmp_demon_bar;
		tmp = (154.0/100.0)*tmp;
		width = (int) tmp;
		bar = SDL_CreateRGBSurface(SDL_HWSURFACE, width, 9, 32, 0,0,0,0);
		if(bar==NULL) {
			error("Null pointer", "game");
			return 1;
		}
		SDL_FillRect(bar, NULL, SDL_MapRGB(bar->format, 255, 38, 23));
		if(demon_bar==100) {
			if(angel_bar<100) {
				anim_bar_z += 100;
				if(anim_bar_z>255)
					anim_bar_z = 0;
			}
			if(anim_bar_z<128)
				SDL_SetAlpha(bar, SDL_SRCALPHA, 0);
			else
				SDL_SetAlpha(bar, SDL_SRCALPHA, 255);
		}
		blit_image(bar, 11, 36, screen);*/

		
		// Refresh the screen
		SDL_Flip(screen);
		
	}
	
	// TODO : frees
	SDL_Quit();
	return 0;
}


/**
 *
 */
void increase_score(state_e state) {
	if(state==DEMON) {
		nb_demon++;
		tmp_demon_bar = demon_bar;
		if(demon_bar>=100) {
			demon_bar = 100; // TODO : power up
			if(angel_bar<100)
				anim_bar_z = 0;
		} else
			demon_bar = demon_bar + (BASE_SCORE/10) + ((BASE_SCORE/10) * (chaine/2));	
	} else {
		nb_angel++;
		tmp_angel_bar = angel_bar;
		if(angel_bar>=100) {
			angel_bar = 100; // TODO : power up
			if(demon_bar<100)
				anim_bar_z = 0;
		} else
			angel_bar = angel_bar + (BASE_SCORE/10) + ((BASE_SCORE/10) * (chaine/2));
	}
	if(old_state==state)
		chaine++;
	else
		chaine = 0;
	score = score + BASE_SCORE + (BASE_SCORE * chaine);
	old_state = state;
}


/**
 *
 */
void display_title(SDL_Surface *screen) {
	if(screen==NULL) {
		error("Null pointer", "display_title");
		return;
	}
	blit_image(title, 0, 0, screen);
	SDL_Flip(screen);
#ifdef PSP
	SceCtrlData	pad;
	int done = FALSE;
	while(!done) 
	{
		sceCtrlReadBufferPositive (&pad, 1);
		//if(pad.Buttons & PSP_CTRL_TRIANGLE)
		//	return TRUE;
		if (pad.Buttons & PSP_CTRL_CROSS) {
			return;
		}
	}	
#else
	SDL_Event event;
	int done = FALSE;
	while(!done) 
	{
		while(SDL_PollEvent(&event)) {
			switch(event.type) {
				case SDL_QUIT:
					return;
					break;
				case SDL_KEYDOWN:
				{
					switch(event.key.keysym.sym) {
						case SDLK_SPACE:
							return;
							break;
						default:
							break;
					}
				}
			}
		}
	}
#endif	
}
	

/**
 *
 */
void display_gameover(SDL_Surface *screen) {
	
	if(screen==NULL) {
		error("Null pointer", "display_gameover");
		return;
	}
	SDL_Surface *background = NULL;
	background = SDL_CreateRGBSurface(SDL_HWSURFACE, SCREEN_W, SCREEN_H, 32, 0,0,0,0);
	if(background==NULL) {
		error("Null pointer", "display_gameover");
		return;
	}
	SDL_FillRect(background, NULL, SDL_MapRGB(background->format, 255, 255, 255));
	SDL_SetAlpha(background, SDL_SRCALPHA, 128);
	blit_image(background, 0, 0, screen);
	
	background = SDL_CreateRGBSurface(SDL_HWSURFACE, SCREEN_W/4+2, SCREEN_H/4+2, 32, 0,0,0,0);
	if(background==NULL) {
		error("Null pointer", "display_gameover");
		return;
	}
	SDL_FillRect(background, NULL, SDL_MapRGB(background->format, 0, 0, 0));
	blit_image(background, SCREEN_W/2-background->w/2, SCREEN_H/2-background->h/2-30, screen);
	
	background = SDL_CreateRGBSurface(SDL_HWSURFACE, SCREEN_W/4, SCREEN_H/4, 32, 0,0,0,0);
	if(background==NULL) {
		error("Null pointer", "display_gameover");
		return;
	}
	SDL_FillRect(background, NULL, SDL_MapRGB(background->format, 255, 255, 255));
	blit_image(background, SCREEN_W/2-background->w/2, SCREEN_H/2-background->h/2-30, screen);
	
	blit_image(demon_mini, SCREEN_W/2-25, 85, screen);
	blit_image(angel_mini, SCREEN_W/2+35, 85, screen);
	blit_int(nb_demon, SCREEN_W/2-30-25, 80, font_20, screen);
	blit_int(nb_angel, SCREEN_W/2+30-25, 80, font_20, screen);
	blit_text("Score", SCREEN_W/2-40, 100, font_20, screen);
	blit_int(score, SCREEN_W/2-30-20, 115, font_20, screen);
	
	SDL_Flip(screen);
	
#ifdef PSP
	SceCtrlData	pad;
	int done = FALSE;
	while(!done) 
	{
		sceCtrlReadBufferPositive (&pad, 1);
		if (pad.Buttons & PSP_CTRL_TRIANGLE) {
			return;
		}
	}	
#else
	SDL_Event event;
	int done = FALSE;
	while(!done) 
	{
		while(SDL_PollEvent(&event)) {
			switch(event.type) {
				case SDL_QUIT:
					return;
					break;
				case SDL_KEYDOWN:
				{
					switch(event.key.keysym.sym) {
						case SDLK_RETURN:
							return;
							break;
						default:
							break;
					}
				}
			}
		}
	}
#endif

}


/**
 *
 */
void move_up(void) {
	orient = UP;
	if(pos_y>0 && monster[pos_x][pos_y-1]==NONE) {
		pos_y--;
	}	
}


/**
 *
 */
void move_down(void) {
	orient = DOWN;
	if(pos_y<NB_CASE_H-1 && monster[pos_x][pos_y+1]==NONE) { 
		pos_y++;
	}
}


/**
 *
 */
void move_right(void) {
	orient = RIGHT;
	if(pos_x<NB_CASE_W-1 && monster[pos_x+1][pos_y]==NONE) {
		pos_x++;
	}
}


/**
 *
 */
void move_left(void) {
	orient = LEFT;
	if(pos_x>0 && monster[pos_x-1][pos_y]==NONE) {
		pos_x--;
	}
}


/**
 *
 */
void change_state_demon(void) {
	if(state==DEMON) {
		animation_light = TRUE;
		draw_msg = ANGEL;
	}
	state = ANGEL;
}


/**
 *
 */
void change_state_angel(void) {
	if(state==ANGEL) {
		animation_light = TRUE;
		draw_msg = DEMON;
	}
	state = DEMON;
}


/**
 *
 */
void monster_touch(void) {
	
	if(orient==UP && pos_y>0 && (monster[pos_x][pos_y-1]==DEMON || monster[pos_x][pos_y-1]==ANGEL)) {
		if(state==monster[pos_x][pos_y-1]) {
			increase_score(monster[pos_x][pos_y-1]);
			monster[pos_x][pos_y-1] = NONE;
			animation_death = TRUE;
			anim_death_pos.x = pos_x;
			anim_death_pos.y = pos_y-1;
		}
	} else if(orient==DOWN && pos_y<NB_CASE_H && (monster[pos_x][pos_y+1]==DEMON || monster[pos_x][pos_y+1]==ANGEL)) {
		if(state==monster[pos_x][pos_y+1]) {
			increase_score(monster[pos_x][pos_y+1]);
			monster[pos_x][pos_y+1] = NONE;
			animation_death = TRUE;
			anim_death_pos.x = pos_x;
			anim_death_pos.y = pos_y+1;
		}
	} else if(orient==LEFT && pos_x>0 && (monster[pos_x-1][pos_y]==DEMON || monster[pos_x-1][pos_y]==ANGEL)) {
		if(state==monster[pos_x-1][pos_y]) {
			increase_score(monster[pos_x-1][pos_y]);
			monster[pos_x-1][pos_y] = NONE;
			animation_death = TRUE;
			anim_death_pos.x = pos_x-1;
			anim_death_pos.y = pos_y;
			
		}
	} else if(orient==RIGHT && pos_x<NB_CASE_W && (monster[pos_x+1][pos_y]==DEMON || monster[pos_x+1][pos_y]==ANGEL)) {
		if(state==monster[pos_x+1][pos_y]) {
			increase_score(monster[pos_x+1][pos_y]);
			monster[pos_x+1][pos_y] = NONE;
			animation_death = TRUE;
			anim_death_pos.x = pos_x+1;
			anim_death_pos.y = pos_y;
		}
	}
	if(animation_death==TRUE) {
		anim_death_y = 0;
		alpha_death = 255;
		anim_death_state = state;
		animation_death = ACTIVE;
	}
}


/**
 *
 */
#ifdef PSP
int psp_event_listener(void) {
	if(timer_state(&timer_move, 50*MS)) {
		timer_restart(&timer_move);
		if(animation==TRUE || animation==ACTIVE) {
			return FALSE;
		} else {
			SceCtrlData	pad;
			sceCtrlReadBufferPositive (&pad, 1);
			if(pad.Buttons & PSP_CTRL_TRIANGLE)
				return TRUE;
			} else if (pad.Buttons & PSP_CTRL_UP) {
				move_up();
			} else if (pad.Buttons & PSP_CTRL_DOWN) {
				move_down();	
			} else if (pad.Buttons & PSP_CTRL_RIGHT) {
				move_right();
			} else if (pad.Buttons & PSP_CTRL_LEFT) {
				move_left();		
			} else if (pad.Buttons & PSP_CTRL_CROSS) {
				monster_touch();
			} else if (pad.Buttons & PSP_CTRL_SQUARE) {
				change_state_demon();
			} else if (pad.Buttons & PSP_CTRL_CIRCLE) {
				change_state_angel();
			}
		}	
}
	return FALSE;
}
#else
int basic_event_listener(void) {
	SDL_Event event;
	if(timer_state(&timer_move, 50*MS)) {
		timer_restart(&timer_move);
	while(SDL_PollEvent(&event)) {
		if(animation==TRUE || animation==ACTIVE) {
			break;
		}
		switch(event.type) {
			case SDL_QUIT:
				return TRUE;
				break;
			case SDL_KEYDOWN:
			{
				switch(event.key.keysym.sym) {
					case SDLK_UP:
						move_up();
						break;
					case SDLK_DOWN:
						move_down();
						break;
					case SDLK_RIGHT:
						move_right();
						break;
					case SDLK_LEFT:
						move_left();
						break;
					case SDLK_a:
						change_state_demon();
						break;
					case SDLK_z:	
						change_state_angel();
						break;
					case SDLK_SPACE:
						monster_touch();
						break;
					default:
						break;
				}					
			}
		}    
	}
	}
	return FALSE;
}
#endif

